#pragma once

#define LIST_INCREMENT 10;

template <class T>
class SnakeVector
{
private:
	T * m_data;//pointer to the allocated data for the vector
	int m_size;//number of valid elements that the caller thinks we have
	int m_allocated;//actual number of elements that we can use
public:
	SnakeVector();
	T get(int a_index); //returns a value from the list
	void set(int a_index, T a_value); //sets a value in the list
	void add(T a_value); //adds new value to end of list, increases size if necessary
	int size();//returns the size of the list
	T * getRawList();//returns the list
	T * getRawData(int a_index);//returns the data
	T * getHead(); //returns the head of the list
	T * getTail(); //returns the end of the list
	void setSize(int a_size);//set the size of the vector
	void remove(int a_pos);//removes an element from the list
	void clear();

};

//default constructor
template <class T>
SnakeVector<T>::SnakeVector()
{
	m_data = 0;
	m_size = 0;
	m_allocated = 0;
}

//returns a value from the list
template <class T>
T SnakeVector<T>::get(int a_index)
{
	return m_data[a_index];
}

//sets a value in the list
template <class T>
void SnakeVector<T>::set(int a_index, T a_value)
{
	m_data[a_index] = a_value;
}

//adds a new value to the end of the list, increases size if necessary
template <class T>
void SnakeVector<T>::add(T a_value)
{
	//if no list exists
	if(m_data == 0)
	{
		//create the list
		m_allocated = LIST_INCREMENT;
		m_data = new T[m_allocated];
	}
	//if list is full
	if(m_size >= m_allocated)
	{
		//create a larger list
		int newListSize = m_allocated + LIST_INCREMENT;
		T * newList = new T[newListSize];
		//copy contents of old list
		for(int i = 0; i < m_allocated; ++i)
		{
			newList[i] = m_data[i];
		}
		//delete old list
		delete m_data;
		//save new list
		m_data = newList;
		m_allocated = newListSize;
	}
	//add the value
	m_data[m_size] = a_value;
	m_size++;
}

//returns the current size of the list
template <class T>
int SnakeVector<T>::size()
{
	return m_size;
}
//returns the list
template <class T>
T * SnakeVector<T>::getRawList()
{
	return m_data;
}
//returns the data
template <class T>
T * SnakeVector<T>::getRawData(int a_index)
{
	return &m_data[a_index];
}
//returns the head of the list
template <class T>
T * SnakeVector<T>::getHead()
{
	//if(m_size > 0)//if a list has been created
	{
		return &m_data[0]; //return first element in the list
	}
}
//returns the end of the list
template <class T>
T * SnakeVector<T>::getTail()
{
	if(m_size > 0) //if the list has at least one element
	{
		return &m_data[m_size-1]; //return the last element in the list
	}
	else
	{
		return &m_data[0];
	}
}
//set the size of the vector
template <class T>
void SnakeVector<T>::setSize(int a_size)
{
	m_size = a_size;
}
//removes an element from the list
template <class T>
void SnakeVector<T>::remove(int a_pos)
{
	//move every element up one
	for(int i = a_pos; i< m_size - 1; ++i)
	{
		m_data[i] = m_data[i+1];
	}
	//reduce the size of the list
	setSize(size() -1);	
}
//release memory
template <class T>
void SnakeVector<T>::clear()
{
	delete m_data;

	m_data = 0;
	m_size = 0;
	m_allocated = 0;
}